#include "types.h"
#include "compiler_abstraction.h"
#include "adl_uart.h"
#include "adl_pin_connect_block.h"
#include "adl_vic.h"

#include "../config/hal_uart_config.h"
#include "hal_uart.h"



// ******************** GLOBAL VARIABLES ***********************

////////////////////////////////////////////////////////////////
/// Uart 0 handlers											 ///
////////////////////////////////////////////////////////////////
#if (UART0_ENABLE == TRUE) & (UART0_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
void (*hal_uart0_dataTransmittedInterruptHandler)(void *args);
void *hal_uart0_dataTransmittedInterruptArgument;
#endif

#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
void (*hal_uart0_dataReceivedInterruptHandler)(void *args);
void *hal_uart0_dataReceivedInterruptArgument;
#endif

#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
void (*hal_uart0_dataErrorInterruptHandler)(void *args);
void *hal_uart0_dataErrorInterruptArgument;
#endif

////////////////////////////////////////////////////////////////
/// Uart 2 handlers											 ///
////////////////////////////////////////////////////////////////
#if (UART3_ENABLE == TRUE) & (UART3_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
void (*hal_uart2_dataTransmittedInterruptHandler)(void *args);
void *hal_uart2_dataTransmittedInterruptArgument;
#endif

#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
void (*hal_uart2_dataReceivedInterruptHandler)(void *args);
void *hal_uart2_dataReceivedInterruptArgument;
#endif

#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
void (*hal_uart2_dataErrorInterruptHandler)(void *args);
void *hal_uart2_dataErrorInterruptArgument;
#endif

////////////////////////////////////////////////////////////////
/// Uart 3 handlers											 ///
////////////////////////////////////////////////////////////////
#if (UART3_ENABLE == TRUE) & (UART3_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
void (*hal_uart3_dataTransmittedInterruptHandler)(void *args);
void *hal_uart3_dataTransmittedInterruptArgument;
#endif

#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
void (*hal_uart3_dataReceivedInterruptHandler)(void *args);
void *hal_uart3_dataReceivedInterruptArgument;
#endif

#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
void (*hal_uart3_dataErrorInterruptHandler)(void *args);
void *hal_uart3_dataErrorInterruptArgument;
#endif

////////////////////////////////////////////////////////////////
/// Enabled uarts											 ///
////////////////////////////////////////////////////////////////
const hal_uart_UartNumber hal_uart_UARTS[] = {
// UART0
#if (UART0_ENABLE == TRUE)
	UART0
#if (UART2_ENABLE == TRUE || UART3_ENABLE == TRUE)
	,
#endif
#endif
// UART2
#if (UART2_ENABLE == TRUE)
	UART2
#if (UART3_ENABLE == TRUE)
	,
#endif
#endif
// UART3
#if (UART3_ENABLE == TRUE)
	UART3
#endif
};

// *************************** BODY ****************************

////////////////////////////////////////////////////////////////
/// Uart 0 interrupt routine								 ///
////////////////////////////////////////////////////////////////
#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_INTERRUPT == TRUE)
void hal_uart0_interruptRoutine(void)
{
	U8 interruptID;

	interruptID = adl_uart_GET_INTERRUPT_ID(UART0);

	if (interruptID == IIR_RLS)
	{
		if(adl_uart_IS_OVERRUN_ERROR(UART0)
			|| adl_uart_IS_PARITY_ERROR(UART0)
			|| adl_uart_IS_FRAMING_ERROR(UART0)
			|| adl_uart_IS_RX_FIFO_ERROR(UART0)
			|| adl_uart_IS_BREAK_INTERRUPT(UART0))
		{
		  	U8 Dummy = adl_uart_READ_RECEIVED_DATA(UART0);
#if UART0_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE
			hal_uart0_dataErrorInterruptHandler(hal_uart0_dataErrorInterruptArgument);
#endif
		}
		else if (adl_uart_IS_RECEIVE_DATA_READY(UART0))
		{
#if UART0_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		  	hal_uart0_dataReceivedInterruptHandler(hal_uart0_dataReceivedInterruptArgument);
#endif
		}
	}
	else if (interruptID == IIR_RDA)
	{
#if UART0_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		hal_uart0_dataReceivedInterruptHandler(hal_uart0_dataReceivedInterruptArgument);
#endif
	}
	else if (interruptID == IIR_THRE)
	{
		if (adl_uart_IS_TRANSMISSION_READY(UART0))
		{
#if UART0_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE
			hal_uart0_dataTransmittedInterruptHandler(hal_uart0_dataTransmittedInterruptArgument);
#endif
		}
	}
}
#endif

////////////////////////////////////////////////////////////////
/// Uart 2 interrupt routine								 ///
////////////////////////////////////////////////////////////////
#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_INTERRUPT == TRUE)
void hal_uart2_interruptRoutine(void)
{
	U8 interruptID;

	interruptID = adl_uart_GET_INTERRUPT_ID(UART2);

	if (interruptID == IIR_RLS)
	{
		if(adl_uart_IS_OVERRUN_ERROR(UART2)
			|| adl_uart_IS_PARITY_ERROR(UART2)
			|| adl_uart_IS_FRAMING_ERROR(UART2)
			|| adl_uart_IS_RX_FIFO_ERROR(UART2)
			|| adl_uart_IS_BREAK_INTERRUPT(UART2))
		{
		  	U8 Dummy = adl_uart_READ_RECEIVED_DATA(UART2);
#if UART2_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE
			hal_uart2_dataErrorInterruptHandler(hal_uart2_dataErrorInterruptArgument);
#endif
		}
		else if (adl_uart_IS_RECEIVE_DATA_READY(UART2))
		{
#if UART2_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		  	hal_uart2_dataReceivedInterruptHandler(hal_uart2_dataReceivedInterruptArgument);
#endif
		}
	}
	else if (interruptID == IIR_RDA)
	{
#if UART2_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		hal_uart2_dataReceivedInterruptHandler(hal_uart2_dataReceivedInterruptArgument);
#endif
	}
	else if (interruptID == IIR_THRE)
	{
		if (adl_uart_IS_TRANSMISSION_READY(UART2))
		{
#if UART2_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE
			hal_uart2_dataTransmittedInterruptHandler(hal_uart2_dataTransmittedInterruptArgument);
#endif
		}
	}
}
#endif

////////////////////////////////////////////////////////////////
/// Uart 3 interrupt routine								 ///
////////////////////////////////////////////////////////////////
#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_INTERRUPT == TRUE)
void hal_uart3_interruptRoutine(void)
{
	U8 interruptID;

	interruptID = adl_uart_GET_INTERRUPT_ID(UART3);

	if (interruptID == IIR_RLS)
	{
		if(adl_uart_IS_OVERRUN_ERROR(UART3)
			|| adl_uart_IS_PARITY_ERROR(UART3)
			|| adl_uart_IS_FRAMING_ERROR(UART3)
			|| adl_uart_IS_RX_FIFO_ERROR(UART3)
			|| adl_uart_IS_BREAK_INTERRUPT(UART3))
		{
		  	U8 Dummy = adl_uart_READ_RECEIVED_DATA(UART3);
#if UART3_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE
			hal_uart3_dataErrorInterruptHandler(hal_uart3_dataErrorInterruptArgument);
#endif
		}
		else if (adl_uart_IS_RECEIVE_DATA_READY(UART3))
		{
#if UART3_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		  	hal_uart3_dataReceivedInterruptHandler(hal_uart3_dataReceivedInterruptArgument);
#endif
		}
	}
	else if (interruptID == IIR_RDA)
	{
#if UART3_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		hal_uart3_dataReceivedInterruptHandler(hal_uart3_dataReceivedInterruptArgument);
#endif
	}
	else if (interruptID == IIR_THRE)
	{
		if (adl_uart_IS_TRANSMISSION_READY(UART3))
		{
#if UART3_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE
			hal_uart3_dataTransmittedInterruptHandler(hal_uart3_dataTransmittedInterruptArgument);
#endif
		}
	}
}
#endif

////////////////////////////////////////////////////////////////
/// Obtain number of enabled uarts							 ///
////////////////////////////////////////////////////////////////
U8 hal_uart_getNumberOfUarts(void)
{
	return sizeof(hal_uart_UARTS)/sizeof(hal_uart_UARTS[0]);
}

////////////////////////////////////////////////////////////////
/// Obtain enabled uarts									 ///
////////////////////////////////////////////////////////////////
hal_uart_UartNumber *hal_uart_getUarts(void)
{
	return (hal_uart_UartNumber *) hal_uart_UARTS;
}

////////////////////////////////////////////////////////////////
/// Install handler of data transmitted interrupt			 ///
////////////////////////////////////////////////////////////////
void hal_uart_installDataTransmittedInterruptHandler(hal_uart_UartNumber uart, void (*handler)(void *args), void *handlerArgument)
{
#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
	if(uart == UART0)
	{
		hal_uart0_dataTransmittedInterruptHandler = handler;
		hal_uart0_dataTransmittedInterruptArgument = handlerArgument;
	}
#endif

#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
	if(uart == UART2)
	{
		hal_uart2_dataTransmittedInterruptHandler = handler;
		hal_uart2_dataTransmittedInterruptArgument = handlerArgument;
	}
#endif

#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
	if(uart == UART3)
	{
		hal_uart3_dataTransmittedInterruptHandler = handler;
		hal_uart3_dataTransmittedInterruptArgument = handlerArgument;
	}
#endif
}

////////////////////////////////////////////////////////////////
/// Install handler of data received interrupt				 ///
////////////////////////////////////////////////////////////////
void hal_uart_installDataReceivedInterruptHandler(hal_uart_UartNumber uart, void (*handler)(void *args), void *handlerArgument)
{
#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
	if(uart == UART0)
	{
		hal_uart0_dataReceivedInterruptHandler = handler;
		hal_uart0_dataReceivedInterruptArgument = handlerArgument;
	}
#endif

#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
	if(uart == UART2)
	{
		hal_uart2_dataReceivedInterruptHandler = handler;
		hal_uart2_dataReceivedInterruptArgument = handlerArgument;
	}
#endif

#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
	if(uart == UART3)
	{
		hal_uart3_dataReceivedInterruptHandler = handler;
		hal_uart3_dataReceivedInterruptArgument = handlerArgument;
	}
#endif
}

////////////////////////////////////////////////////////////////
/// Install handler of data received interrupt				 ///
////////////////////////////////////////////////////////////////
void hal_uart_installDataErrorInterruptHandler(hal_uart_UartNumber uart, void (*handler)(void *args), void *handlerArgument)
{
#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
	if(uart == UART0)
	{
		hal_uart0_dataErrorInterruptHandler = handler;
		hal_uart0_dataErrorInterruptArgument = handlerArgument;
	}
#endif

#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
	if(uart == UART2)
	{
		hal_uart2_dataErrorInterruptHandler = handler;
		hal_uart2_dataErrorInterruptArgument = handlerArgument;
	}
#endif

#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
	if(uart == UART3)
	{
		hal_uart3_dataErrorInterruptHandler = handler;
		hal_uart3_dataErrorInterruptArgument = handlerArgument;
	}
#endif
}

////////////////////////////////////////////////////////////////
/// Uart initialization										 ///
////////////////////////////////////////////////////////////////
void hal_uart_init(void)
{
	// Uart 0 ---------------------------
#if (UART0_ENABLE == TRUE)
	adl_pin_connect_block_CONFIG_RXD0();
	adl_pin_connect_block_CONFIG_TXD0();

  	adl_uart_SET_DATA_LENGTH(UART0, UART0_DATA_LENGTH);
  	adl_uart_SET_ENABLE_PARITY(UART0, UART0_ENABLE_PARITY_CHECKING);
#if (UART0_ENABLE_PARITY_CHECKING == TRUE)
  	adl_uart_SET_PARITY(UART0, UART0_PARITY);
#endif
  	adl_uart_SET_STOP_BIT(UART0, UART0_STOP_BIT);
  	adl_uart_ENABLE_BAUDRATE_DLA(UART0);
  	adl_uart_SET_FRACTIONAL_BAUDRATE_DIVISOR(UART0, UART0_FRACTIONAL_BAUDRATE_DIVISOR);
  	adl_uart_SET_FRACTIONAL_BAUDRATE_MULTIPLIER(UART0, UART0_FRACTIONAL_BAUDRATE_MULTIPLIER);
  	adl_uart_SET_BAUDRATE_DIVISOR(UART0, UART0_BAUDRATE_DIVISOR);
  	adl_uart_DISABLE_BAUDRATE_DLA(UART0);

#if (UART0_ENABLE_INTERRUPT == TRUE)
	adl_vic_INSTALL_IRQ(UART0_INT, hal_uart0_interruptRoutine, UART0_INTERRUPT_PRIORITY);
#endif

	adl_uart_ENABLE_RDA_INTERRUPT(UART0);
	adl_uart_ENABLE_THRE_INTERRUPT(UART0);
	adl_uart_ENABLE_RLS_INTERRUPT(UART0);
#endif

	// Uart 2 ---------------------------
#if (UART2_ENABLE == TRUE)
	adl_pin_connect_block_CONFIG_RXD2();
	adl_pin_connect_block_CONFIG_TXD2();

  	adl_uart_SET_DATA_LENGTH(UART2, UART2_DATA_LENGTH);
  	adl_uart_SET_ENABLE_PARITY(UART2, UART2_ENABLE_PARITY_CHECKING);
#if (UART2_ENABLE_PARITY_CHECKING == TRUE)
  	adl_uart_SET_PARITY(UART2, UART2_PARITY);
#endif
  	adl_uart_SET_STOP_BIT(UART2, UART2_STOP_BIT);
  	adl_uart_ENABLE_BAUDRATE_DLA(UART2);
  	adl_uart_SET_FRACTIONAL_BAUDRATE_DIVISOR(UART2, UART2_FRACTIONAL_BAUDRATE_DIVISOR);
  	adl_uart_SET_FRACTIONAL_BAUDRATE_MULTIPLIER(UART2, UART2_FRACTIONAL_BAUDRATE_MULTIPLIER);
  	adl_uart_SET_BAUDRATE_DIVISOR(UART2, UART2_BAUDRATE_DIVISOR);
  	adl_uart_DISABLE_BAUDRATE_DLA(UART2);

#if (UART2_ENABLE_INTERRUPT == TRUE)
	adl_vic_INSTALL_IRQ(UART2_INT, hal_uart2_interruptRoutine, UART2_INTERRUPT_PRIORITY);
#endif

	adl_uart_ENABLE_RDA_INTERRUPT(UART2);
	adl_uart_ENABLE_THRE_INTERRUPT(UART2);
	adl_uart_ENABLE_RLS_INTERRUPT(UART2);
#endif

	// Uart 3 ---------------------------
#if (UART3_ENABLE == TRUE)
	adl_pin_connect_block_CONFIG_RXD3();
	adl_pin_connect_block_CONFIG_TXD3();

  	adl_uart_SET_DATA_LENGTH(UART3, UART3_DATA_LENGTH);
  	adl_uart_SET_ENABLE_PARITY(UART3, UART3_ENABLE_PARITY_CHECKING);
#if (UART3_ENABLE_PARITY_CHECKING == TRUE)
  	adl_uart_SET_PARITY(UART3, UART3_PARITY);
#endif
  	adl_uart_SET_STOP_BIT(UART3, UART3_STOP_BIT);
  	adl_uart_ENABLE_BAUDRATE_DLA(UART3);
  	adl_uart_SET_FRACTIONAL_BAUDRATE_DIVISOR(UART3, UART3_FRACTIONAL_BAUDRATE_DIVISOR);
  	adl_uart_SET_FRACTIONAL_BAUDRATE_MULTIPLIER(UART3, UART3_FRACTIONAL_BAUDRATE_MULTIPLIER);
  	adl_uart_SET_BAUDRATE_DIVISOR(UART3, UART3_BAUDRATE_DIVISOR);
  	adl_uart_DISABLE_BAUDRATE_DLA(UART3);

#if (UART3_ENABLE_INTERRUPT == TRUE)
	adl_vic_INSTALL_IRQ(UART3_INT, hal_uart3_interruptRoutine, UART3_INTERRUPT_PRIORITY);
#endif

	adl_uart_ENABLE_RDA_INTERRUPT(UART3);
	adl_uart_ENABLE_THRE_INTERRUPT(UART3);
	adl_uart_ENABLE_RLS_INTERRUPT(UART3);
#endif
}

////////////////////////////////////////////////////////////////
/// Send byte												 ///
////////////////////////////////////////////////////////////////
void hal_uart_sendByte(U8 uart, U8 byte)
{
#if (UART0_ENABLE == TRUE)
	if(uart == UART0)
	{
		adl_uart_SEND_DATA(UART0, byte);
	}
#endif

#if (UART2_ENABLE == TRUE)
	if(uart == UART2)
	{
		adl_uart_SEND_DATA(UART2, byte);
	}
#endif

#if (UART03ENABLE == TRUE)
	if(uart == UART3)
	{
		adl_uart_SEND_DATA(UART3, byte);
	}
#endif
}

////////////////////////////////////////////////////////////////
/// Receive byte											 ///
////////////////////////////////////////////////////////////////
U8 hal_uart_receiveByte(U8 uart)
{
	U8 result;

#if (UART0_ENABLE == TRUE)
	if(uart == UART0)
	{
		result = adl_uart_READ_RECEIVED_DATA(UART0);
	}
#endif

#if (UART2_ENABLE == TRUE)
	if(uart == UART2)
	{
		result = adl_uart_READ_RECEIVED_DATA(UART2);
	}
#endif

#if (UART3_ENABLE == TRUE)
	if(uart == UART3)
	{
		result = adl_uart_READ_RECEIVED_DATA(UART3);
	}
#endif

	return result;
}
